package kr.co.goodwilldd;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.context.request.async.DeferredResult;

public class ChatParticipant {

	private static final Logger logger = LoggerFactory
			.getLogger(ChatParticipant.class);
	private final String user;

	private final String topic;

	private final List<ChatMessage> messageCache = new ArrayList<ChatMessage>();

	private DeferredResult<List<ChatMessage>> deferredResult;

	private final Object lock = new Object();

	/**
	 * Create a ChatParticipant instance.
	 */
	public ChatParticipant(String user, String topic) {
		this.user = user;
		this.topic = topic;
	}

	public String getUser() {
		return user;
	}

	public String getTopic() {
		return topic;
	}

	/**
	 * Process the message by setting the DeferredResult or if a DeferredResult
	 * is not available (between polling requests?), save the message.
	 * 
	 * <p>
	 * Note: this method is thread-safe since some threads may poll for new
	 * messages while other threads post messages.
	 */
	public void processMessage(ChatMessage message) {
		synchronized (lock) {
			if (this.deferredResult != null) {
				try {
					logger.debug("{}", Arrays.asList(message));
					
					this.deferredResult.setResult(Arrays.asList(message));
					return;
				} catch (Exception e) {
					// fall through and save message
					System.out.println("times out");
				} finally {
					this.deferredResult = null;
				}
			}
			this.messageCache.add(message);
		}
	}

	/**
	 * Return saved messages or if none are available return {@code null} and
	 * save the DeferredResult to process the messages when they become
	 * available.
	 * 
	 * <p>
	 * Note: this method is thread-safe since some threads may poll for new
	 * messages while other threads post messages.
	 */
	public List<ChatMessage> getMessagesWhenAvailable(
			DeferredResult deferredResult) {
		synchronized (lock) {
			if (this.messageCache.isEmpty()) {
				this.deferredResult = deferredResult;
				return null;
			} else {
				ArrayList<ChatMessage> result = new ArrayList<ChatMessage>(
						this.messageCache);
				this.messageCache.clear();
				return result;
			}
		}
	}

	@Override
	public String toString() {
		return "ChatParticipant [user=" + user + ", topic=" + topic + "]";
	}
}
